package com.easy.aspect;

import com.easy.annotation.LogMethod;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * AOP切面类，用于实现日志记录的横切逻辑
 * 作用：拦截被@LogMethod注解标记的方法，在方法执行前后自动记录日志
 */
// @Component：将该类注册为Spring容器中的Bean
@Component
// @Aspect：标记该类为AOP切面类，包含切入点和通知逻辑
@Aspect
public class EasyAspect {
    /**
     * 环绕通知（@Around）：在目标方法执行前后都能执行逻辑，且能控制目标方法是否执行
     * value = "@annotation(logmethod)"：切入点表达式，拦截所有被@LogMethod注解标记的方法
     * 并将注解实例作为参数传入（logmethod参数与注解绑定）
     */
@Around(value="@annotation(logmethod)")
    public Object recordLog(ProceedingJoinPoint point, LogMethod logmethod) throws Throwable {
        Object obj = null;// 用于存储目标方法的返回值

        StringBuilder strb= new StringBuilder();// 日志内容拼接器

        // 1. 从注解中获取配置参数
        String serviceName = logmethod.serviceName();//注解上标记的属性
        boolean decordParam = logmethod.recordParam();
        boolean decordReturn = logmethod.recordReturn();

        // 2. 获取目标方法的签名信息（通过ProceedingJoinPoint获取方法元数据）
        MethodSignature methodsignature =(MethodSignature) point.getSignature();
        //获取方法名
        String methodName = methodsignature.getMethod().getName();

        // 3. 拼接日志前缀（服务名、方法名
        strb.append("[");
        strb.append(serviceName);
        strb.append("]");
        strb.append("  method:");
        strb.append(methodName);
    // 4. 若需要记录参数，先拼接参数占位（实际参数可通过point.getArgs()获取，这里简化处理）
        if(decordParam){
            strb.append("  params:");
        }
     // 5. 执行目标方法（ProceedingJoinPoint的proceed()方法触发原始方法执行）
        obj = point.proceed();
    // 6. 若需要记录返回值，拼接返回值信息
        if(decordReturn){
            strb.append("  return:");
            strb.append(obj);
        }
    // 7. 拼接当前时间并输出日志
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        strb.append("  [");
        strb.append(sdf.format(date));
        strb.append("]");
        System.out.println(strb.toString());

        return obj;
    }
}
